<?php
require_once 'Sabai/Controller/Front.php';

class Xigg_Main extends Sabai_Controller_Front
{
	function Xigg_Main()
	{
		parent::Sabai_Controller_Front('Index', 'Xigg_Main_', dirname(__FILE__) . '/Main');
		$this->addFilter('global');
        $this->addControllerFilter(array('DeleteCommentForm',
                                         'MoveCommentForm',
                                         'EditTrackbackForm',
                                         'DeleteTrackbackForm'), 'isModerator');
        $this->addControllerFilter(array('DeleteNodeForm', 'PublishNodeForm'), 'isEditor');
        $this->addControllerFilter(array('ShowVoteForm',
                                         'SubmitVote'), 'isAuthenticated');
        $this->addControllerFilter(array('SubmitNodeForm',
                                         'EditNodeForm'), 'isSubmitter');
        $this->addControllerFilter(array('ShowUpcomingNodes',
                                         'ShowUpcomingNodesByTag'), 'isUpcomingFeatureEnabled');
        $this->addControllerFilter(array('SubmitCommentForm',
                                         'SubmitCommentReplyForm',
                                         'ShowCommentReplyForm',
                                         'ShowComments',
                                         'ShowComment'), 'isCommentFeatureEnabled');
        $this->addControllerFilter(array('ShowTrackbacks',
                                         'ShowTrackback',
                                         'PostTrackback'), 'isTrackbackFeatureEnabled');
        $this->addControllerFilter(array('ShowVotes',
                                         'ShowVoteForm',
                                         'SubmitVote',
                                         'ShowVote'), 'isVotingFeatureEnabled');
        $this->addControllerFilter(array('SubmitCommentForm',
                                         'SubmitCommentReplyForm',
                                         'ShowCommentReplyForm',
                                         'EditCommentForm'), 'isCommentAllowed');
	}

	function _getRoutes()
	{
        $routes = array(
        			'node/upcoming' => array('controller' => 'ShowUpcomingNodes'),
        			'node/:node_id/votes' => array('controller'   => 'ShowVotes',
                                                   'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/voteform' => array('controller'   => 'ShowVoteForm',
                                                      'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/vote' => array('controller'   => 'SubmitVote',
                                                  'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/comments' => array('controller'   => 'ShowComments',
                                                      'requirements' => array(':node_id' => '\d+')),
                    'node/:node_id/commentform' => array('controller'   => 'ShowCommentForm',
                                                         'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/comment' => array('controller'   => 'SubmitCommentForm',
                                                     'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/trackbacks' => array('controller'   => 'ShowTrackbacks',
                                                        'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/publish' => array('controller'   => 'PublishNodeForm',
                                                     'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/edit' => array('controller'   => 'EditNodeForm',
                                                  'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/delete' => array('controller'   => 'DeleteNodeForm',
                                                    'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id/trackback' => array('controller'   => 'PostTrackback',
                                                       'requirements' => array(':node_id' => '\d+')),
        			'node/:node_id' => array('controller'   => 'ShowNode',
                                             'requirements' => array(':node_id' => '\d+')),
                    'node' => array('controller'   => 'ShowNodes'),
        			'comment/:comment_id/replyform' => array('controller'   => 'ShowCommentReplyForm',
                                                             'requirements' => array(':comment_id' => '\d+')),
        			'comment/:comment_id/reply' => array('controller'   => 'SubmitCommentReplyForm',
                                                         'requirements' => array(':comment_id' => '\d+')),
        			'comment/:comment_id/replies' => array('controller'   => 'ShowCommentReplies',
                                                           'requirements' => array(':comment_id' => '\d+')),
        			'comment/:comment_id/delete' => array('controller'   => 'DeleteCommentForm',
                                                          'requirements' => array(':comment_id' => '\d+')),
        			'comment/:comment_id/edit' => array('controller'   => 'EditCommentForm',
                                                        'requirements' => array(':comment_id' => '\d+')),
        			'comment/:comment_id/move' => array('controller'   => 'MoveCommentForm',
                                                        'requirements' => array(':comment_id' => '\d+')),
        			'comment/:comment_id' => array('controller'   => 'ShowComment',
                                                   'requirements' => array(':comment_id' => '\d+')),
        			'tag/:tag_name/upcoming' => array('controller'   => 'ShowUpcomingNodesByTag',
                                                      'requirements' => array(':tag_name' => '.+')),
        			'tag/:tag_name' => array('controller'   => 'ShowNodesByTag',
                                             'requirements' => array(':tag_name' => '.+')),
                    'tag' => array('controller' => 'ListTags'),
                    'trackback/:trackback_id/delete' => array('controller'   => 'DeleteTrackbackForm',
                                                            'requirements' => array(':trackback_id' => '\d+')),
                    'trackback/:trackback_id/edit' => array('controller'   => 'EditTrackbackForm',
                                                            'requirements' => array(':trackback_id' => '\d+')),
        			'trackback/:trackback_id' => array('controller'   => 'ShowTrackback',
                                                       'requirements' => array(':trackback_id' => '\d+')),
        			'vote/:vote_id' => array('controller'   => 'ShowVote',
                                             'requirements' => array(':vote_id' => '\d+')),
                    'plugin/:plugin_name' => array('controller'   => 'Plugin',
                                                   'requirements' => array(':plugin_name' => '^[a-zA-Z]+[a-zA-Z0-9_]*[a-zA-Z0-9]+$')),
        			'submit' => array('controller' => 'SubmitNodeForm'),
        			'rss' => array('controller' => 'RSS'),
        			'login' => array('controller' => 'Login'),
        			'logout' => array('controller' => 'Logout')
        		  );
        return $routes;
	}

	/**
	 * Override the parent method to invoke plugins
	 *
	 * @param string $controllerName
	 * @param Sabai_Context $context
	 */
	function _doExecuteController($controllerName, &$context)
	{
	    $plugin_mngr =& $this->_locator->getService('PluginManager');
        $plugin_mngr->dispatch('ExecuteController', array($controllerName, &$context));
        parent::_doExecuteController($controllerName, $context);
	}

	function &getNodeById(&$request, $nodeIdVar = 'node_id')
    {
        $ret = false;
        if (0 < $node_id = $request->getAsInt($nodeIdVar)) {
            $model =& $this->_locator->getService('Model');
            $node_r =& $model->getRepository('Node');
            if (false !== $node =& $node_r->fetchById($node_id)) {
                $ret =& $node;
            }
        }
        return $ret;
    }

    function linkTagsToNode(&$node, $tagsStr)
    {
        $model =& $this->_locator->getService('Model');
        $tag_names = array();
        mb_regex_encoding(SABAI_CHARSET);
        foreach (explode(',', $tagsStr) as $tag_name) {
            // convert encoding specific chars and then trim
            $tag_name = mb_convert_kana($tag_name, 'a', SABAI_CHARSET);
            $tag_name = trim(mb_ereg_replace(_(' '), ' ', $tag_name));
            // remove redundant spaces and invalid characters
            $tag_name = preg_replace(array('/\s\s+/', "[\r\n\t]", '/[\/~]/'), array(' ', ' ', ''), $tag_name);
            $tag_names[strtolower($tag_name)] = $tag_name;
        }
        $tag_r =& $model->getRepository('Tag');
        $tags_existing =& $tag_r->getExistingTags(array_keys($tag_names));
        while ($tag_existing =& $tags_existing->getNext()) {
            $tag_existing->linkNode($node);
            unset($tag_names[strtolower($tag_existing->getLabel())]);
        }
        foreach ($tag_names as $tag_name) {
            $tag =& $model->create('Tag');
            $tag->set('name', $tag_name);
            $tag->linkNode($node);
        }
        return $model->commit();
    }

    function globalBeforeFilter(&$context)
    {
        $plugin_mngr =& $this->_locator->getService('PluginManager');
        $plugin_mngr->dispatch('EnterMain', array(&$context));
    }

    function globalAfterFilter(&$context)
    {
        $plugin_mngr =& $this->_locator->getService('PluginManager');
        $plugin_mngr->dispatch('ExitMain', array(&$context));
    }

    function isAuthenticatedBeforeFilter(&$context)
    {
        if (!$context->user->isAuthenticated()) {
            $context->response->setError(_('You must login to perform this operation'), Sabai_URL::get('/login'));
            $context->response->send();
            exit;
        }
    }

    function isModeratorBeforeFilter(&$context)
    {
        if (!$context->user->isInRole(array(XIGG_ROLE_ADMIN, XIGG_ROLE_MODERATOR))) {
            $context->response->setError(_('Access denied'), Sabai_URL::get());
            $context->response->send();
            exit;
        }
    }

    function isEditorBeforeFilter(&$context)
    {
        if (!$context->user->isInRole(array(XIGG_ROLE_ADMIN, XIGG_ROLE_EDITOR))) {
            $context->response->setError(_('Access denied'), Sabai_URL::get());
            $context->response->send();
            exit;
        }
    }

    function isSubmitterBeforeFilter(&$context)
    {
        if (!$context->user->isInRole(array(XIGG_ROLE_ADMIN, XIGG_ROLE_EDITOR, XIGG_ROLE_WRITER, XIGG_ROLE_SUBMITTER))) {
            $context->response->setError(_('Access denied'), Sabai_URL::get());
            $context->response->send();
            exit;
        }
    }

    function isCommentAllowedBeforeFilter(&$context)
    {
        if (!$context->user->isAuthenticated()) {
            if (!$context->config->get('guestCommentsAllowed')) {
                $context->response->setError(_('You must login to post comments'), Sabai_URL::get('/login'));
                $context->response->send();
                exit;
            }
        }
    }

    function isUpcomingFeatureEnabledBeforeFilter(&$context)
    {
    	$this->_isFeatureEnabledBeforeFilter('useUpcomingFeature', $context);
    }

    function isCommentFeatureEnabledBeforeFilter(&$context)
    {
    	$this->_isFeatureEnabledBeforeFilter('useCommentFeature', $context);
    }

    function isTrackbackFeatureEnabledBeforeFilter(&$context)
    {
    	$this->_isFeatureEnabledBeforeFilter('useTrackbackFeature', $context);
    }

    function isVotingFeatureEnabledBeforeFilter(&$context)
    {
    	$this->_isFeatureEnabledBeforeFilter('useVotingFeature', $context);
    }

    function _isFeatureEnabledBeforeFilter($feature, &$context)
    {
        if (!$context->config->get($feature)) {
            $context->response->setError(_('Access denied'), Sabai_URL::get());
            $context->response->send();
            exit;
        }
    }
}